package com.example.hxds.bff.customer.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.codingapi.txlcn.tc.annotation.LcnTransaction;
import com.example.hxds.bff.customer.controller.form.*;
import com.example.hxds.bff.customer.fegin.*;
import com.example.hxds.bff.customer.service.OrderService;
import com.example.hxds.common.exception.HxdsException;
import com.example.hxds.common.util.ConstantPropertiesUtils;
import com.example.hxds.common.util.HttpClient;
import com.example.hxds.common.util.PageUtils;
import com.example.hxds.common.util.R;
import com.example.hxds.common.wxpay.MyWXPayConfig;
import com.example.hxds.common.wxpay.WXPay;
import com.example.hxds.common.wxpay.WXPayUtil;
import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Service
@Slf4j
public class OrderServiceImpl implements OrderService {

    @Resource
    private MpsServiceApi mpsServiceApi;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private SnmServiceApi snmServiceApi;
    @Resource
    private RuleServiceApi ruleServiceApi;
    @Resource
    private OdrServiceApi odrServiceApi;
    @Autowired
    private DrServiceApi drServiceApi;
    @Autowired
    private VhrServiceApi vhrServiceApi;
    @Autowired
    private CstServiceApi cstServiceApi;
    @Resource
    private MyWXPayConfig myWXPayConfig;

    @Override
    public HashMap createNewOrder(CreateNewOrderForm form) {
        Long customerId = form.getCustomerId();
        String startPlace = form.getStartPlace();
        String startPlaceLatitude = form.getStartPlaceLatitude();
        String startPlaceLongitude = form.getStartPlaceLongitude();
        String endPlace = form.getEndPlace();
        String endPlaceLatitude = form.getEndPlaceLatitude();
        String endPlaceLongitude = form.getEndPlaceLongitude();
        String favourFee = form.getFavourFee();

        EstimateOrderMileageAndMinuteForm form_1 = new EstimateOrderMileageAndMinuteForm();
        form_1.setMode("driving");
        form_1.setStartPlaceLatitude(startPlaceLatitude);
        form_1.setStartPlaceLongitude(startPlaceLongitude);
        form_1.setEndPlaceLatitude(endPlaceLatitude);
        form_1.setEndPlaceLongitude(endPlaceLongitude);
        R r = mpsServiceApi.estimateOrderMileageAndMinute(form_1);
        HashMap map = (HashMap) r.get("result");
        String mileage = MapUtil.getStr(map, "mileage");
        Integer minute = MapUtil.getInt(map, "minute");

        /**
         * 重新估算订单金额
         */
        EstimateOrderChargeForm form_2 = new EstimateOrderChargeForm();
        form_2.setMileage(mileage);
        form_2.setTime(new DateTime().toTimeStr());
        r = ruleServiceApi.estimateOrderCharge(form_2);
        map = (HashMap) r.get("result");
        String expectsFee = MapUtil.getStr(map, "amount");
        String chargeRuleId = MapUtil.getStr(map, "chargeRuleId");
        short baseMileage = MapUtil.getShort(map, "baseMileage");
        String baseMileagePrice = MapUtil.getStr(map, "baseMileagePrice");
        String exceedMileagePrice = MapUtil.getStr(map, "exceedMileagePrice");
        short baseMinute = MapUtil.getShort(map, "baseMinute");
        String exceedMinutePrice = MapUtil.getStr(map, "exceedMinutePrice");
        short baseReturnMileage = MapUtil.getShort(map, "baseReturnMileage");
        String exceedReturnPrice = MapUtil.getStr(map, "exceedReturnPrice");

        //TODO 搜索适合接单的司机
        SearchBefittingDriverAboutOrderForm form_3 = new SearchBefittingDriverAboutOrderForm();
        form_3.setStartPlaceLatitude(startPlaceLatitude);
        form_3.setStartPlaceLongitude(startPlaceLongitude);
        form_3.setEndPlaceLatitude(endPlaceLatitude);
        form_3.setEndPlaceLongitude(endPlaceLongitude);
        form_3.setMileage(mileage);
        r = mpsServiceApi.searchBefittingDriverAboutOrder(form_3);
        ArrayList<HashMap> list = (ArrayList<HashMap>) r.get("result");

        HashMap result = new HashMap() {{
            put("count", 0);
        }};

        if (list.size() > 0) {
            InsertOrderForm insertOrderForm = new InsertOrderForm();
            //UUID字符串,充当订单号,微信支付时候会用上
            insertOrderForm.setUuid(IdUtil.simpleUUID());
            insertOrderForm.setCustomerId(customerId);
            insertOrderForm.setStartPlace(startPlace);
            insertOrderForm.setStartPlaceLatitude(startPlaceLatitude);
            insertOrderForm.setStartPlaceLongitude(startPlaceLongitude);
            insertOrderForm.setEndPlace(endPlace);
            insertOrderForm.setEndPlaceLatitude(endPlaceLatitude);
            insertOrderForm.setEndPlaceLongitude(endPlaceLongitude);
            insertOrderForm.setExpectsMileage(mileage);
            insertOrderForm.setExpectsFee(expectsFee);
            insertOrderForm.setFavourFee(favourFee);
            insertOrderForm.setDate(new DateTime().toDateStr());
            insertOrderForm.setChargeRuleId(Long.parseLong(chargeRuleId));
            insertOrderForm.setCarPlate(form.getCarPlate());
            insertOrderForm.setCarType(form.getCarType());
            insertOrderForm.setBaseMileage(baseMileage);
            insertOrderForm.setBaseMileagePrice(baseMileagePrice);
            insertOrderForm.setExceedMileagePrice(exceedMileagePrice);
            insertOrderForm.setBaseMinute(baseMinute);
            insertOrderForm.setExceedMinutePrice(exceedMinutePrice);
            insertOrderForm.setBaseReturnMileage(baseReturnMileage);
            insertOrderForm.setExceedReturnPrice(exceedReturnPrice);
            r = odrServiceApi.insertOrder(insertOrderForm);
            String orderId = MapUtil.getStr(r, "result");

            //TODO  发送订单消息给相关的司机
            SendNewOrderMessageForm sendNewOrderMessageForm = new SendNewOrderMessageForm();
            String[] driverContent = new String[list.size()];
            for (int i = 0; i < list.size(); i++) {
                HashMap one = list.get(i);
                String driverId = MapUtil.getStr(one, "driverId");
                String distance = MapUtil.getStr(one, "distance");
                distance = new BigDecimal(distance).setScale(1, RoundingMode.CEILING).toString();
                driverContent[i] = driverId + "#" + distance;
            }
            sendNewOrderMessageForm.setDriversContent(driverContent);
            sendNewOrderMessageForm.setOrderId(Long.parseLong(orderId));
            sendNewOrderMessageForm.setFrom(startPlace);
            sendNewOrderMessageForm.setTo(endPlace);
            sendNewOrderMessageForm.setExpectsFee(expectsFee);
            //里程转化成保留小数点后一位
            mileage = new BigDecimal(mileage).setScale(1, RoundingMode.CEILING).toString();
            sendNewOrderMessageForm.setMileage(mileage);
            sendNewOrderMessageForm.setMinute(minute);
            sendNewOrderMessageForm.setFavourFee(favourFee);
            snmServiceApi.sendNewOrderMessageAsync(sendNewOrderMessageForm); //异步发送消息
            result.put("orderId", orderId);
            result.replace("count", list.size());
        }
        return result;
    }

    @Override
    public Integer searchOrderStatus(SearchOrderStatusForm form) {
        R r = odrServiceApi.searchOrderStatus(form);
        Integer status = MapUtil.getInt(r, "result");
        return status;
    }

    @Override
    @Transactional
    @LcnTransaction
    public String deleteUnAcceptOrder(DeleteUnAcceptOrderForm form) {
        R r = odrServiceApi.deleteUnAcceptOrder(form);
        String result = MapUtil.getStr(r, "result");
        return result;
    }

    @Override
    public HashMap hasCustomerCurrentOrder(HasCustomerCurrentOrderForm form) {
        R r = odrServiceApi.hasCustomerCurrentOrder(form);
        HashMap map = (HashMap) r.get("result");
        return map;
    }

    @Override
    public HashMap searchOrderForMoveById(SearchOrderForMoveByIdForm form) {
        R r = odrServiceApi.searchOrderForMoveById(form);
        HashMap result = (HashMap) r.get("result");
        return result;
    }

    @Override
    public boolean confirmArriveStartPlace(ConfirmArriveStartPlaceForm form) {
        R r = odrServiceApi.confirArriveStartPlace(form);
        Boolean result = MapUtil.getBool(r, "result");
        return result;
    }

    @Override
    public HashMap searchOrderById(SearchOrderByIdForm form) {
        R r = odrServiceApi.searchOrderById(form);
        HashMap map = (HashMap) r.get("result");
        Long driverId = MapUtil.getLong(map, "driverId");
        if (driverId != null) {
            SearchDriverBriefInfoForm searchDriverBriefInfoForm = new SearchDriverBriefInfoForm();
            searchDriverBriefInfoForm.setDriverId(driverId);
            r = drServiceApi.searchDriverBriefInfo(searchDriverBriefInfoForm);
            HashMap temp = (HashMap) r.get("result");
            map.putAll(temp);
            Integer status = MapUtil.getInt(map, "status");

            if (status == 6) {
                SearchBestUnUseVoucherForm searchBestUnUseVoucherForm = new SearchBestUnUseVoucherForm();
                searchBestUnUseVoucherForm.setCustomerId(form.getCustomerId());
                BigDecimal total = new BigDecimal(MapUtil.getStr(map, "total"));
                searchBestUnUseVoucherForm.setAmount(total);
                r = vhrServiceApi.searchBestUnUseVoucher(searchBestUnUseVoucherForm);
                HashMap result = (HashMap) r.get("result");
                map.put("voucher", result);
            }

            HashMap cmtMap = new HashMap();
            if (status >= 7) {
                SearchCommentByOrderIdForm searchCommentByOrderIdForm = new SearchCommentByOrderIdForm();
                searchCommentByOrderIdForm.setOrderId(form.getOrderId());
                searchCommentByOrderIdForm.setCustomerId(form.getCustomerId());
                r = odrServiceApi.searchCommentByOrderId(searchCommentByOrderIdForm);
                if (r.containsKey("result")) {
                    cmtMap = (HashMap) r.get("result");
                } else {
                    cmtMap.put("rate", 5);
                }
            }
            map.put("comment", cmtMap);
            return map;
        }
        return null;
    }


    @Override
    @Transactional
    @LcnTransaction
    public HashMap createwxPayment(long orderId, long customerId, Long customerVoucherId, Long voucherId) {
        //查询账单是否位6 ,其他状态都不可以生成支付订单
        ValidCanPayOrderForm validCanPayOrderForm = new ValidCanPayOrderForm();
        validCanPayOrderForm.setOrderId(orderId);
        validCanPayOrderForm.setCustomerId(customerId);
        R r = odrServiceApi.validCanPayOrder(validCanPayOrderForm);
        HashMap map = (HashMap) r.get("result");
        String amount = MapUtil.getStr(map, "realFee");
        String uuid = MapUtil.getStr(map, "uuid");
        long driverId = MapUtil.getLong(map, "driverId");
        String discount = "0.00";

        if (voucherId != null && customerVoucherId!=null) {
            //查看代金卷 是否可以使用
            UseVoucherForm useVoucherForm = new UseVoucherForm();
            useVoucherForm.setId(customerId);
            useVoucherForm.setVoucherId(voucherId);
            useVoucherForm.setOrderId(orderId);
            useVoucherForm.setAmount(amount);
            useVoucherForm.setCustomerId(customerId);
            r = vhrServiceApi.useVoucher(useVoucherForm);
            discount = MapUtil.getStr(r, "result");
        }

        if (new BigDecimal(amount).compareTo(new BigDecimal(discount)) == -1) {
            throw new HxdsException("总金额不能小于优惠券面额");
        }

        //修改实付金额
        amount = NumberUtil.sub(amount, discount).toString();
        UpdateBillPaymentForm updateBillPaymentForm = new UpdateBillPaymentForm();
        updateBillPaymentForm.setOrderId(orderId);
        updateBillPaymentForm.setRealPay(amount);
        updateBillPaymentForm.setVoucherFee(discount);
        odrServiceApi.updateBillPayment(updateBillPaymentForm);

        //查询用户的openId
        SearchCustomerOpenIdForm searchCustomerOpenIdForm = new SearchCustomerOpenIdForm();
        searchCustomerOpenIdForm.setCustomerId(customerId);
        r = cstServiceApi.searchCustomerOpenId(searchCustomerOpenIdForm);
        String customerOpenId = MapUtil.getStr(r, "result");

        //查询司机的openId字符串
        SearchDriverOpenIdForm searchDriverOpenIdForm = new SearchDriverOpenIdForm();
        searchDriverOpenIdForm.setDriverId(driverId);
        r = drServiceApi.searchDriverOpenId(searchDriverOpenIdForm);
        String driverOpenId = MapUtil.getStr(r, "result");

        //TODO 创建支付订单

        try {
            Map paramMap = new HashMap();
            paramMap.put("appid", myWXPayConfig.getAppID());
            paramMap.put("mch_id", myWXPayConfig.getMchID());
            paramMap.put("nonce_str", WXPayUtil.generateNonceStr());
            paramMap.put("body", "代驾费");
            paramMap.put("out_trade_no", uuid);//随机字符串
            paramMap.put("total_fee", "1");  //金额 0.01 元，为了测试使用
            paramMap.put("spbill_create_ip", "127.0.0.1");
            paramMap.put("notify_url", "http://6udvaw.natappfree.cc/hxds-odr/order/recieveMessage/" + orderId);
            paramMap.put("trade_type", "NATIVE");
            paramMap.put("attach", driverOpenId);
            //4.调用微信生成二维码接口，httpclient调用
            HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder");
            //client设置参数
            client.setXmlParam(WXPayUtil.generateSignedXml(paramMap, ConstantPropertiesUtils.PARTNERKEY));
            client.setHttps(true);
            client.post();
            //5.返回相关数据(是一段xml格式的内容)
            String xml = client.getContent();
            //转换map集合
            Map<String, String> resultMap = WXPayUtil.xmlToMap(xml);
            System.out.println("resultMap：" + resultMap);
            String prepayId = resultMap.get("prepay_id");

            if (prepayId != null) {
                UpdateOrderPrepayIdForm updateOrderPrepayIdForm = new UpdateOrderPrepayIdForm();
                updateOrderPrepayIdForm.setOrderId(orderId);
                updateOrderPrepayIdForm.setPrepayId(prepayId);
                odrServiceApi.updateOrderPrepayId(updateOrderPrepayIdForm);
                //准备生成数字签名
                map.clear();
                map.put("appid", myWXPayConfig.getAppID());
                String timeStamp = new Date().getTime() + "";
                map.put("timeStamp", timeStamp);
                map.put("nonceStr", WXPayUtil.generateNonceStr());
                map.put("package", "prepay_id=" + prepayId);
                map.put("signType", "MD5");

                //生成数据签名
                String paySign = WXPayUtil.generateSignature(map, myWXPayConfig.getKey());

                map.clear();
                map.put("package", "prepay_id=" + prepayId);
                map.put("timeStamp", timeStamp);
                map.put("nonceStr", WXPayUtil.generateNonceStr());
                map.put("paySign", paySign);
                map.put("codeUrl", resultMap.get("code_url"));
                map.put("uuid", uuid); //uuid 用于付款成功后,移动端主动请求更新充值状态

//                HashMap orderPayMap = new HashMap();
//                orderPayMap.put("outTradeNo", uuid);
//                orderPayMap.put("prepayId",prepayId);
//                String orderPayKey = "orderPay#" + orderId;
//                redisTemplate.opsForValue().set(orderPayKey, orderPayMap);
                return map;
            } else {
                log.error("创建支付订单失败");
                throw new HxdsException("创建支付订单失败");
            }
        } catch (Exception e) {
            log.error("创建支付订单失败", e);
            throw new HxdsException("创建支付订单失败");
        }
    }

    @Override
    public String updateOrderAboutPayment(UpdateOrderAboutPaymentForm form) {
        R r = odrServiceApi.updateOrderAboutPayment(form);
        String result = MapUtil.getStr(r, "result");
        return result;
    }

    @Override
    public PageUtils searchCustomerOrderByPage(SearchCustomerOrderByPageForm form) {
        R r = odrServiceApi.searchCustomerOrderByPage(form);
        HashMap map = (HashMap) r.get("result");
        PageUtils pageUtils = BeanUtil.toBean(map, PageUtils.class);
        return pageUtils;
    }


}


